using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using ClickOnceMaster.Helpers;
using ClickOnceMaster.Pages;
using ClickOnceMaster.Properties;

namespace ClickOnceMaster
{
    /// <summary>
    /// Represents a wizard main form.
    /// </summary>
    public partial class WizardForm : Form
    {
        #region Instance fields

        private readonly object _currentPageSynchronizer = new object();

        /// <summary>
        /// The list of wizard pages.
        /// </summary>
        private readonly LinkedList<WizardPage> _pages = new LinkedList<WizardPage>();

        /// <summary>
        /// The current wizard page.
        /// </summary>
        private LinkedListNode<WizardPage> _currentPage;

        #endregion

        #region .ctors

        /// <summary>
        /// Initializes a new <see cref="WizardForm"/> instance.
        /// </summary>
        public WizardForm()
        {
            InitializeComponent();

            DisableButtons();

            CreatePages();

            LoadPage(_pages.First);
        }

        #endregion

        #region Instance properties

        /// <summary>
        /// Gets the indication which specifies whether the wizard displays the first page.
        /// </summary>
        public bool IsStart
        {
            get { return _currentPage == _pages.First; }
        }

        /// <summary>
        /// Gets the indication which specifies whether the wizard displays the last page.
        /// </summary>
        public bool IsFinish
        {
            get { return _currentPage == _pages.Last; }
        }

        #endregion

        #region Instance methods

        #region Form overrides

        ///<summary>
        /// Overrides the <see cref="System.Windows.Forms.Form.OnFormClosing"></see> method.
        ///</summary>
        ///<param name="e">A <see cref="T:System.Windows.Forms.FormClosingEventArgs"></see> that contains the event data. </param>
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (IsFinish && btnCancel.Enabled)
            {
                e.Cancel = MessageBox.Show(
                               this,
                               Resources.CancealAndClosingConfirmation,
                               Text,
                               MessageBoxButtons.YesNo,
                               MessageBoxIcon.Question,
                               MessageBoxDefaultButton.Button1) == DialogResult.No;
            }
            else if (!IsFinish)
            {
                e.Cancel = MessageBox.Show(
                               this,
                               Resources.ClosingConfirmation,
                               Text,
                               MessageBoxButtons.YesNo,
                               MessageBoxIcon.Question,
                               MessageBoxDefaultButton.Button1) == DialogResult.No;
            }
            base.OnFormClosing(e);
        }

        ///<summary>
        /// Overrides the <see cref="System.Windows.Forms.Form.OnLoad"></see> method.
        ///</summary>
        ///<param name="e">A <see cref="T:System.Windows.Forms.FormClosingEventArgs"></see> that contains the event data. </param>
        protected override void OnLoad(EventArgs e)
        {
            Bitmap bm = FixedSize(Resources.Gear, pbLogo.Width, pbLogo.Height);
            pbLogo.Image = bm;

            base.OnLoad(e);
        }

        #endregion

        #region Event handlers

        /// <summary>
        /// Handles the "Cancel" button click.
        /// </summary>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (IsFinish)
            {
                if (MessageBox.Show(
                        this,
                        Resources.CancealConfirmation,
                        Text,
                        MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    
                }
            }
            else
            {
                Close();
            }
        }

        /// <summary>
        /// Handles the "Finish" button click.
        /// </summary>
        private void btnFinish_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Handles the "Back" button click.
        /// </summary>
        private void btnBack_Click(object sender, EventArgs e)
        {
            LoadPage(_currentPage != null ? _currentPage.Previous : _pages.First);
        }

        /// <summary>
        /// Handles the "Next" button click.
        /// </summary>
        private void btnNext_Click(object sender, EventArgs e)
        {
            if (_currentPage != null && _currentPage.Value.ValidatePage())
            {
                LoadPage(_currentPage != null ? _currentPage.Next : _pages.First);
            }
        }

        /// <summary>
        /// Handles the <see cref="BackgroundWorker.DoWork"/> event.
        /// </summary>
        private void bwLoadPage_DoWork(object sender, DoWorkEventArgs e)
        {
            lock (_currentPageSynchronizer)
            {
                if (_currentPage != null)
                {
                    _currentPage.Value.LoadPage();
                }
            }
        }

        /// <summary>
        /// Handles the <see cref="BackgroundWorker.RunWorkerCompleted"/> event.
        /// </summary>
        private void bwLoadPage_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            EnableButtons();

            Cursor = Cursors.Default;
            if (e.Error != null)
            {
                ExceptionHelper.HandleException(e.Error);
            }
        }

        #endregion

        #region Auxiliary methods

        /// <summary>
        /// Creates the wizard pages.
        /// </summary>
        private void CreatePages()
        {
            _pages.AddLast(new LinkedListNode<WizardPage>(new WelcomePage()));
            _pages.AddLast(new LinkedListNode<WizardPage>(new SourcePage()));
            _pages.AddLast(new LinkedListNode<WizardPage>(new FilesPage()));
            _pages.AddLast(new LinkedListNode<WizardPage>(new ApplicationPage()));
            _pages.AddLast(new LinkedListNode<WizardPage>(new ReadyPage()));
            _pages.AddLast(new LinkedListNode<WizardPage>(new RunPage()));
        }

        /// <summary>
        /// Loads the specified wizard <paramref name="page"/> into the wizard surface.
        /// </summary>
        /// <param name="page">The wizard page is being loaded.</param>
        private void LoadPage(LinkedListNode<WizardPage> page)
        {
            Cursor = page.Value.WhaitCursor;

            lock (_currentPageSynchronizer)
            {
                ShowPage(page);
            }
            DisableButtons();

            bwLoadPage.RunWorkerAsync();
        }

        /// <summary>
        /// Shows the specified wizard page.
        /// </summary>
        /// <param name="page">The wizard page is being displayed.</param>
        private void ShowPage(LinkedListNode<WizardPage> page)
        {
            try
            {
                panPages.SuspendLayout();

                if (_currentPage != null)
                {
                    _currentPage.Value.Visible = false;
                }

                _currentPage = page;

                if (_currentPage != null)
                {
                    lblTitle.Text = _currentPage.Value.Text;

                    _currentPage.Value.Visible = true;

                    if (!panPages.Controls.Contains(_currentPage.Value))
                    {
                        panPages.Controls.Add(_currentPage.Value);
                        _currentPage.Value.Dock = DockStyle.Fill;
                    }
                }
                else
                {
                    lblTitle.Text = string.Empty;
                }
            }
            finally
            {
                panPages.ResumeLayout();
            }
        }

        /// <summary>
        /// Disables the wizard buttons.
        /// </summary>
        private void DisableButtons()
        {
            btnBack.Enabled =
                btnNext.Enabled =
                //btnCancel.Enabled =
                btnFinish.Enabled = false;
            if (_currentPage != null)
            {
                if (!IsFinish)
                {
                    btnCancel.Enabled = false;
                }
            }
        }

        /// <summary>
        /// Enables the wizard buttons.
        /// </summary>
        private void EnableButtons()
        {
            btnBack.Enabled = !IsStart && !IsFinish;
            btnNext.Enabled =
                btnCancel.Enabled = !IsFinish;
            btnFinish.Enabled = IsFinish;
        }

        /// <summary>
        /// Resizing bitmap to target size
        /// </summary>
        private Bitmap FixedSize(Bitmap imgPhoto, int width, int h)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent;
            float nPercentW;
            float nPercentH;

            nPercentW = (width/(float) sourceWidth);
            nPercentH = (h/(float) sourceHeight);
            if (nPercentH < nPercentW)
            {
                nPercent = nPercentH;
                destX = Convert.ToInt16((width -
                                         (sourceWidth*nPercent))/2);
            }
            else
            {
                nPercent = nPercentW;
                destY = Convert.ToInt16((h -
                                         (sourceHeight*nPercent))/2);
            }

            int destWidth = (int) (sourceWidth*nPercent);
            int destHeight = (int) (sourceHeight*nPercent);

            Bitmap bmPhoto = new Bitmap(width, h);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                                  imgPhoto.VerticalResolution);

            using (Graphics grPhoto = Graphics.FromImage(bmPhoto))
            {
                grPhoto.Clear(Color.FromArgb(0, 252, 219, 173)); // Back color.
                grPhoto.InterpolationMode = InterpolationMode.Bilinear; //Interpolation

                grPhoto.DrawImage(imgPhoto,
                                  new Rectangle(destX, destY, destWidth, destHeight),
                                  new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                                  GraphicsUnit.Pixel);
            }
            return bmPhoto;
        }

        #endregion

        #endregion
    }
}